package OOP2;
/**
 * 内部类专题示例
 * 包含：成员内部类、匿名内部类、静态嵌套类
 */
public class InnerClassExample {

    // Outer是一个普通类，
    // 而Inner是一个Inner Class，它与普通类有个最大的不同，就是Inner Class的实例不能单独存在，必须依附于一个Outer Class的实例
    //      观察Java编译器编译后的.class文件可以发现，Outer类被编译为Outer.class，而Inner类被编译为Outer$Inner.class。
    //
    // 这是因为Inner Class除了有一个this指向它自己，还隐含地持有一个Outer Class实例，可以用Outer.this访问这个实例。
    // 所以，实例化一个Inner Class不能脱离Outer实例。
    //
    // Inner Class和普通Class相比，除了能引用Outer实例外，还有一个额外的“特权”：就是可以修改Outer Class的private字段，
    // 因为Inner Class的作用域在Outer Class内部，所以能访问Outer Class的private字段和方法。
    //
    //
    public void innerClassDemo() {


        // 创建外部类实例
        Outer outer = new Outer("Outer实例");

        // 创建内部类实例（必须通过外部类实例）
        Outer.Inner inner = outer.new Inner();
        inner.hello(); // 输出外部类实例和静态字段

//        // 创建静态嵌套类实例（不需要外部类实例）
//        Outer.StaticNested staticNested = new Outer.StaticNested();
//        staticNested.hello();

    }

    // ==================== 匿名内部类 ====================

    // 在 Java 中，匿名内部类必须继承某个类或实现某个接口
    // 因为匿名内部类的本质是定义一个没有名字的子类或实现类，并立即创建它的实例。
    //
    // 匿名内部类的语法规则
        //继承一个类：匿名类可以继承一个具体类。
        //实现一个接口：匿名类可以实现一个接口，并需要实现接口的所有抽象方法。
        //匿名内部类不能同时继承类和实现接口。

    /**
     * 接口用于演示匿名内部类：
     * 1. 必须实现接口所有方法
     * 2. 可以访问外部类私有成员
     */
    public interface MyInterface {
        void show(String name, int age);
    }

    /**
     * 包含私有成员的外部类
     */
    public class MyInterfaceOuter {
        private String message = "外部类私有字段";

        private void showPrivateMessage() {
            System.out.println("调用外部类私有方法");
        }

        public void testAnonymousClass() {
            // 创建匿名内部类（同时实现接口和访问外部类成员）
            MyInterface impl = new MyInterface() {
                // 实现接口定义的方法
                @Override
                public void show(String name, int age) {
                    // 访问外部类实例字段
                    System.out.println(name + ":" + age);
                    System.out.println("访问外部类字段: " + message);

                    // 访问外部类方法（两种方式等价）
                    MyInterfaceOuter.this.showPrivateMessage();// 用Outer.this访问外部类的私有方法
                    showPrivateMessage(); // 不用 Outer.this也可以直接访问外部类的私有方法，隐式访问外部类实例
                }
            };

            impl.show("张三", 18);
        }
    }



    // ==================== 成员内部类 ====================
    /**
     * Outer类演示成员内部类：
     * 1. 内部类实例必须依附外部类实例存在
     * 2. 内部类可以访问外部类私有成员
     * 3. 编译后会生成 Outer.class 和 Outer$Inner.class
     */

    class Outer {

        private String name;

        Outer(String name) {
            this.name = name;
        }

        private static final String NAME = "Static Outer"; // 静态私有字段

        // 成员内部类
        class Inner {
            void hello() {
                // 访问外部类实例的私有字段
                System.out.println("访问外部实例字段: Hello, " + Outer.this.name);
                // 直接访问外部类静态私有字段
                System.out.println("访问外部静态字段: " + Outer.NAME);
            }
        }


// ==================== 静态嵌套类 ====================
        /**
         * 静态嵌套类：
         * 1. 不依赖外部类实例（可直接new）
         * 2. 只能访问外部类的静态成员
         * 3. 拥有外部类的private访问权限
         */

        // 静态内部类Static Nested Class是独立类，但拥有Outer Class的private访问权限
            // 因此无法引用Outer.this，但它可以访问Outer的private静态字段和静态方法。
            // 如果把StaticNested移到Outer之外，就失去了访问private的权限

//        static class StaticNested {
//            void hello() {
//                // 可以访问外部类的静态私有字段
//                System.out.println("StaticNested访问: " + Outer.NAME);
//                // System.out.println(name); // 错误！不能访问非静态成员
//            }
//        }

    }
    // ==================== 使用示例 ====================


    public static void main(String[] args) {
        InnerClassExample example = new InnerClassExample();

        System.out.println("==== 成员内部类演示 ====");
        example.innerClassDemo();

        System.out.println("\n==== 匿名内部类演示 ====");
        MyInterfaceOuter outer = example.new MyInterfaceOuter();
        outer.testAnonymousClass();
    }
    /*

    ==== 成员内部类演示 ====
    访问外部实例字段: Hello, Outer实例
    访问外部静态字段: Static Outer
    StaticNested访问: Static Outer

    ==== 匿名内部类演示 ====
    张三:18
    访问外部类字段: 外部类私有字段
    调用外部类私有方法
    调用外部类私有方法

     */
}
